-
Notifications
You must be signed in to change notification settings - Fork 6k
Mention how non-public fields of inherited classes are serialized #47148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels like this deserves a code sample showing how things work.
For example:
[Serializable]
public class BaseClass {
public int PublicIntField;
private int NonPublicIntField;
public BaseClass(int publicIntFieldValue, nonPublicIntFieldValue) {
PublicIntField = publicIntFieldValue;
NonPublicIntField = nonPublicIntFieldValue;
}
}
[Serializable]
public class DerivedClass : BaseClass {
public string PublicStringField;
private string NonPublicStringField;
public DerivedClass(int publicIntFieldValue, int nonPublicIntFieldValue)
: base(publicIntFieldValue, nonPublicIntFieldValue) {
PublicStringField = PublicIntField.ToString();
NonPublicStringField = NonPublicIntField.ToString();
}
}
Then show an example of serializing both a BaseClass
and a DerivedClass
, including what values are contained within each payload.
@@ -20,7 +20,7 @@ The <xref:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter> was fi | |||
|
|||
## Member names | |||
|
|||
In most common scenario, the type is annotated with `[Serializable]` and the serializer uses reflection to serialize **all fields** (both public and non-public) except those that are annotated with `[NonSerialized]`. By default, the serialized member names will match the type's field names. This historically led to incompatibilities when even private fields are renamed on `[Serializable]` types. During migrations away from BinaryFormatter, it becomes necessary to understand how serialized field names were handled and overridden. | |||
In most common scenario, the type is annotated with `[Serializable]` and the serializer uses reflection to serialize **all fields** (both public and non-public) except those that are annotated with `[NonSerialized]`. By default, the serialized member names of public fields will match the type's field names. For non-public fields defined in inherited classes, the member names consist of inherited type name, a `+` sign and the field name (`$InheritedClassName+$nonPublicFieldName`). Serializing field names has historically led to incompatibilities when even private fields are renamed on `[Serializable]` types. During migrations away from BinaryFormatter, it becomes necessary to understand how serialized field names were handled and overridden. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In most common scenario, the type is annotated with `[Serializable]` and the serializer uses reflection to serialize **all fields** (both public and non-public) except those that are annotated with `[NonSerialized]`. By default, the serialized member names of public fields will match the type's field names. For non-public fields defined in inherited classes, the member names consist of inherited type name, a `+` sign and the field name (`$InheritedClassName+$nonPublicFieldName`). Serializing field names has historically led to incompatibilities when even private fields are renamed on `[Serializable]` types. During migrations away from BinaryFormatter, it becomes necessary to understand how serialized field names were handled and overridden. | |
In the most common scenario, the type is annotated with `[Serializable]` and the serializer uses reflection to serialize **all fields** (both public and non-public) except those that are annotated with `[NonSerialized]`. By default, the serialized member names of public fields will match the type's field names. For non-public fields defined in inherited classes, the member names consist of inherited type name, a `+` sign, and the field name (`$InheritedClassName+$nonPublicFieldName`). Serializing field names has historically led to incompatibilities when even private fields are renamed on `[Serializable]` types. During migrations away from BinaryFormatter, it became necessary to understand how serialized field names were handled and overridden. |
Repro:
Source of confusion:
https://github.com/dotnet/runtime/blob/513ff1acc981118e4b981e965dce614c3b8770f5/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/FormatterServices.cs#L42-L44
https://github.com/dotnet/runtime/blob/513ff1acc981118e4b981e965dce614c3b8770f5/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/FormatterServices.cs#L68
https://github.com/dotnet/runtime/blob/513ff1acc981118e4b981e965dce614c3b8770f5/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationFieldInfo.cs#L21
Internal previews